package org.db.ui;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.text.DecimalFormat;
import java.util.List;

import javax.swing.JDialog;
import javax.swing.JOptionPane;

import org.db.Manager;
import org.db.dao.BauwerkslinienDAO;
import org.db.dao.change.AddProjektElement;
import org.db.dao.change.RemoveProjektElement;
import org.db.dao.change.UpdateProjektElement;

/**
 * 
 * @author Lutz
 */
public class BauwerkslinienDialog extends CloseCommitDialog
		implements
			ActionListener,
			KeyListener,
			MouseListener {

	/**
	 * 
	 */
	private static final long serialVersionUID = -666839361311056522L;

	private DecimalFormat format1 = new DecimalFormat("0.000");

	private BauwerkslinienDAO element2Edit = null;

	public BauwerkslinienDialog(JDialog owner) {
		super(owner);
		setModal(true);
		setTitle("Bauwerke");
		initComponents();

	}

	private static final String BauwerkException = "Bitte vervollständigen Sie die Eingaben zum Bauwerk!";

	private static final String EndStationException = "Bitte überprüfen Sie den Wert für die Endstationierung!";

	// Initialisierung der GUI- Elemente
	private void initComponents() {

		jLabel1 = new javax.swing.JLabel();
		jLabel2 = new javax.swing.JLabel();
		jTextBauwerk = new javax.swing.JTextField();
		jLabel3 = new javax.swing.JLabel();
		jTextStationA = new DoubleTextField();
		jLabel4 = new javax.swing.JLabel();
		jLabel5 = new javax.swing.JLabel();
		jTextBesonderh = new javax.swing.JTextField();
		jButtonCancel = new javax.swing.JButton();
		jButtonOK = new javax.swing.JButton();
		jButtonNext = new javax.swing.JButton();
		jLabel6 = new javax.swing.JLabel();
		jTextStationE = new DoubleTextField();
		jLabel7 = new javax.swing.JLabel();
		jLabel8 = new javax.swing.JLabel();
		jTextHoeheBauwerk = new DoubleTextField();
		jLabel9 = new javax.swing.JLabel();
		jScrollPane2 = new javax.swing.JScrollPane();
		table = new BauwerkslinienTable();
		table.addKeyListener(this);
		table.addMouseListener(this);

		// definieren einer beforzugten Frame-Größe
		setPreferredSize(new java.awt.Dimension(750, 400));
		// DialogFrame kann nicht maximiert werden
		setResizable(false);

		// Definition von Eingenschaften der GUI- Elemente
		jLabel1.setFont(new java.awt.Font("Tahoma", 1, 18));
		jLabel1.setText("Bauwerkslinie");

		Double stationAnf = Manager.getInstance().getGleisElemente()
				.get(returnValue).getAnfangsStation();
		jTextStationA.setText(stationAnf.toString());

		jLabel2.setFont(new java.awt.Font("Tahoma", 1, 12));
		jLabel2.setText("Bauwerk");

		jTextBauwerk.setToolTipText("z.B. Rohrdurchlaß, Brücke...");

		jLabel3.setFont(new java.awt.Font("Tahoma", 1, 12));
		jLabel3.setText("Stationierung von");

		jTextStationA.setFocusTraversalPolicyProvider(true);

		jLabel4.setFont(new java.awt.Font("Tahoma", 1, 12));
		jLabel4.setText("m");

		jLabel5.setFont(new java.awt.Font("Tahoma", 1, 12));
		jLabel5.setText("Besonderheiten");

		jTextBesonderh
				.setToolTipText("Wenn bekannt, Besonderheiten und Bemerkungen eingeben.");

		jButtonCancel.setFont(new java.awt.Font("Tahoma", 1, 12));
		jButtonCancel.setText("Abbrechen");
		jButtonCancel
				.setToolTipText("Verwerfen der Eingaben. Zurück zum Auswahlfenster.");
		jButtonCancel.addActionListener(this);
		jButtonCancel.addKeyListener(this);

		jButtonOK.setFont(new java.awt.Font("Tahoma", 1, 12));
		jButtonOK.setText("Eingabe beenden");
		jButtonOK
				.setToolTipText("Prüfen und Speichern der Eingaben. Zurück zum Auswahlfenster.");
		jButtonOK.addActionListener(this);
		jButtonOK.addKeyListener(this);

		jButtonNext.setFont(new java.awt.Font("Tahoma", 1, 12));
		jButtonNext.setText("Hinzufügen");
		jButtonNext
				.setToolTipText("Bauwerk wird gespeichert und Eingabefelder für weitere Eingaben geleert.");
		jButtonNext.addActionListener(this);
		jButtonNext.addKeyListener(this);

		jLabel6.setFont(new java.awt.Font("Tahoma", 1, 12));
		jLabel6.setText("Stationierung bis");

		jTextStationE
				.setToolTipText("Wenn bekannt, Endstationierung des Bawerks eingeben.");

		jLabel7.setFont(new java.awt.Font("Tahoma", 1, 12));
		jLabel7.setText("m");

		jLabel8.setFont(new java.awt.Font("Tahoma", 1, 12));
		jLabel8.setText("Höhe Bauwerk");

		jTextHoeheBauwerk
				.setToolTipText("Wenn bekannt, Höhe des Bauwerks eingeben.");

		jLabel9.setFont(new java.awt.Font("Tahoma", 1, 12));
		jLabel9.setText("m");

		jScrollPane2.setViewportView(table);

		// horizontale und vertikale Ausrichtung der GUI- Komponenten auf dem
		// DialogFrame
		javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
				getContentPane());
		getContentPane().setLayout(layout);
		layout.setHorizontalGroup(layout
				.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGroup(
						layout.createSequentialGroup()
								.addContainerGap()
								.addGroup(
										layout.createParallelGroup(
												javax.swing.GroupLayout.Alignment.LEADING)
												.addGroup(
														layout.createParallelGroup(
																javax.swing.GroupLayout.Alignment.LEADING)
																.addGroup(
																		layout.createSequentialGroup()
																				.addGroup(
																						layout.createParallelGroup(
																								javax.swing.GroupLayout.Alignment.TRAILING)
																								.addComponent(
																										jLabel3)
																								.addComponent(
																										jLabel1)
																								.addComponent(
																										jLabel6))
																				.addPreferredGap(
																						javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																				.addGroup(
																						layout.createParallelGroup(
																								javax.swing.GroupLayout.Alignment.LEADING,
																								false)
																								.addComponent(
																										jTextStationA)
																								.addComponent(
																										jTextStationE,
																										javax.swing.GroupLayout.DEFAULT_SIZE,
																										67,
																										Short.MAX_VALUE))
																				.addPreferredGap(
																						javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																				.addGroup(
																						layout.createParallelGroup(
																								javax.swing.GroupLayout.Alignment.LEADING)
																								.addGroup(
																										layout.createSequentialGroup()
																												.addComponent(
																														jLabel4)
																												.addGap(18,
																														18,
																														18)
																												.addGroup(
																														layout.createParallelGroup(
																																javax.swing.GroupLayout.Alignment.TRAILING)
																																.addComponent(
																																		jLabel5)
																																.addGroup(
																																		layout.createSequentialGroup()
																																				.addComponent(
																																						jLabel2)
																																				.addPreferredGap(
																																						javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																																				.addComponent(
																																						jTextBauwerk,
																																						javax.swing.GroupLayout.PREFERRED_SIZE,
																																						105,
																																						javax.swing.GroupLayout.PREFERRED_SIZE)
																																				.addGap(18,
																																						18,
																																						18)
																																				.addComponent(
																																						jLabel8)))
																												.addPreferredGap(
																														javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																												.addGroup(
																														layout.createParallelGroup(
																																javax.swing.GroupLayout.Alignment.LEADING)
																																.addComponent(
																																		jTextBesonderh,
																																		javax.swing.GroupLayout.PREFERRED_SIZE,
																																		169,
																																		javax.swing.GroupLayout.PREFERRED_SIZE)
																																.addGroup(
																																		layout.createSequentialGroup()
																																				.addComponent(
																																						jTextHoeheBauwerk,
																																						javax.swing.GroupLayout.PREFERRED_SIZE,
																																						79,
																																						javax.swing.GroupLayout.PREFERRED_SIZE)
																																				.addPreferredGap(
																																						javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																																				.addComponent(
																																						jLabel9))))
																								.addComponent(
																										jLabel7)))
																.addGroup(
																		javax.swing.GroupLayout.Alignment.TRAILING,
																		layout.createSequentialGroup()
																				.addComponent(
																						jButtonOK)
																				.addPreferredGap(
																						javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																				.addComponent(
																						jButtonCancel,
																						javax.swing.GroupLayout.PREFERRED_SIZE,
																						120,
																						javax.swing.GroupLayout.PREFERRED_SIZE)))
												.addComponent(
														jScrollPane2,
														javax.swing.GroupLayout.Alignment.TRAILING,
														javax.swing.GroupLayout.DEFAULT_SIZE,
														674, Short.MAX_VALUE)
												.addComponent(
														jButtonNext,
														javax.swing.GroupLayout.Alignment.TRAILING))
								.addContainerGap()));
		layout.setVerticalGroup(layout
				.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
				.addGroup(
						layout.createSequentialGroup()
								.addContainerGap()
								.addComponent(jLabel1)
								.addGap(33, 33, 33)
								.addGroup(
										layout.createParallelGroup(
												javax.swing.GroupLayout.Alignment.BASELINE)
												.addComponent(jLabel3)
												.addComponent(
														jTextStationA,
														javax.swing.GroupLayout.PREFERRED_SIZE,
														javax.swing.GroupLayout.DEFAULT_SIZE,
														javax.swing.GroupLayout.PREFERRED_SIZE)
												.addComponent(jLabel4)
												.addComponent(jLabel2)
												.addComponent(
														jTextBauwerk,
														javax.swing.GroupLayout.PREFERRED_SIZE,
														javax.swing.GroupLayout.DEFAULT_SIZE,
														javax.swing.GroupLayout.PREFERRED_SIZE)
												.addComponent(jLabel8)
												.addComponent(
														jTextHoeheBauwerk,
														javax.swing.GroupLayout.PREFERRED_SIZE,
														javax.swing.GroupLayout.DEFAULT_SIZE,
														javax.swing.GroupLayout.PREFERRED_SIZE)
												.addComponent(jLabel9))
								.addPreferredGap(
										javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addGroup(
										layout.createParallelGroup(
												javax.swing.GroupLayout.Alignment.LEADING)
												.addGroup(
														layout.createParallelGroup(
																javax.swing.GroupLayout.Alignment.BASELINE)
																.addComponent(
																		jLabel6)
																.addComponent(
																		jTextStationE,
																		javax.swing.GroupLayout.PREFERRED_SIZE,
																		javax.swing.GroupLayout.DEFAULT_SIZE,
																		javax.swing.GroupLayout.PREFERRED_SIZE)
																.addComponent(
																		jLabel7))
												.addGroup(
														layout.createParallelGroup(
																javax.swing.GroupLayout.Alignment.BASELINE)
																.addComponent(
																		jLabel5)
																.addComponent(
																		jTextBesonderh,
																		javax.swing.GroupLayout.PREFERRED_SIZE,
																		javax.swing.GroupLayout.DEFAULT_SIZE,
																		javax.swing.GroupLayout.PREFERRED_SIZE)))
								.addPreferredGap(
										javax.swing.LayoutStyle.ComponentPlacement.RELATED,
										30, Short.MAX_VALUE)
								.addComponent(jButtonNext,
										javax.swing.GroupLayout.PREFERRED_SIZE,
										34,
										javax.swing.GroupLayout.PREFERRED_SIZE)
								.addPreferredGap(
										javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addComponent(jScrollPane2,
										javax.swing.GroupLayout.PREFERRED_SIZE,
										138,
										javax.swing.GroupLayout.PREFERRED_SIZE)
								.addPreferredGap(
										javax.swing.LayoutStyle.ComponentPlacement.RELATED)
								.addGroup(
										layout.createParallelGroup(
												javax.swing.GroupLayout.Alignment.BASELINE)
												.addComponent(
														jButtonCancel,
														javax.swing.GroupLayout.PREFERRED_SIZE,
														32,
														javax.swing.GroupLayout.PREFERRED_SIZE)
												.addComponent(
														jButtonOK,
														javax.swing.GroupLayout.PREFERRED_SIZE,
														33,
														javax.swing.GroupLayout.PREFERRED_SIZE))
								.addContainerGap()));

		pack();
		isValidSession();
		setLocationRelativeTo(null);
	}

	public int showBauwerkslinienDialog() {
		setVisible(true);
		return returnValue;
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == jButtonOK) {
			if (isValidSession()) {
				// Manager.getInstance().commit();
				Manager.getInstance().applyChanges();
				setVisible(false);
				dispose();
			} else {
				JOptionPane.showMessageDialog(this,
						"Bitte überprüfen Sie die gelben Fehler!");
			}
		} else if (e.getSource() == jButtonCancel) {
			returnValue = JOptionPane.CANCEL_OPTION;
			askForClosing();

		} else if (e.getSource() == jButtonNext) {
			if (isValidInput()) {
				String bauwerk = jTextBauwerk.getText();
				double stationierungVonInMeter = jTextStationA.getValue();
				double stationierungBisInMeter = (jTextStationE.getValue() == 0)
						? stationierungVonInMeter
						: jTextStationE.getValue();
				double hoeheInMeter = !jTextHoeheBauwerk.getText().isEmpty()
						? Double.valueOf(jTextHoeheBauwerk.getText())
						: 0;
				String besonderheiten = !jTextBesonderh.getText().isEmpty()
						? jTextBesonderh.getText()
						: "";

				BauwerkslinienDAO dao = new BauwerkslinienDAO(bauwerk,
						stationierungVonInMeter, stationierungBisInMeter,
						hoeheInMeter, besonderheiten);
				if (element2Edit != null) {
					table.replaceBauwerkslinienElement(element2Edit, dao);
					Manager.getInstance().addProjektChange(
							new UpdateProjektElement(element2Edit, dao));
					element2Edit = null;
				} else {
					table.addBauwerkslinienElement(dao);
					Manager.getInstance().addProjektChange(
							new AddProjektElement(dao));
				}
				// Manager.getInstance().addDAO2Add(dao);
				clearInput();
				isValidSession();
				returnValue = JOptionPane.OK_OPTION;
			}

		}

	}

	/**
	 * Test ob die Änderungen in der aktuellen Sitzung gültig sind.
	 * 
	 * @return
	 */
	private boolean isValidSession() {
		List<BauwerkslinienDAO> bauwerkslinienElemente = table
				.getBauwerkslinienElemente();
		BauwerkslinienDAO el1;
		BauwerkslinienDAO el2;
		for (int i = 0; i < bauwerkslinienElemente.size() - 1; i++) {
			el1 = bauwerkslinienElemente.get(i);
			el2 = bauwerkslinienElemente.get(i + 1);
			if (el1.getStationierungVonInMeter() == el2
					.getStationierungVonInMeter()) {
				table.highlightCell(i, 0);
				table.highlightCell(i + 1, 0);
				return false;
			}
			if (el1.getStationierungBisInMeter() >= el2
					.getStationierungVonInMeter()) {
				table.highlightCell(i, 1);
				table.highlightCell(i + 1, 0);
				return false;
			}
		}
		table.resetHighlighting();
		return true;
	}

	/**
	 * Leeren und Vorbereiten der Eingabefelder für nächste Eingabe
	 */
	private void clearInput() {
		Double stationNeu = !jTextStationE.getText().isEmpty() ? Double
				.valueOf(jTextStationE.getText()) : Double
				.valueOf(jTextStationA.getText());
		jTextStationA.setText(stationNeu.toString());
		jTextBauwerk.setText("");
		jTextStationE.setText("");
		jTextHoeheBauwerk.setText("");
		jTextBesonderh.setText("");
		jTextStationA.requestFocusInWindow();
	}

	public static String getEingabeError() {
		return BauwerkException;
	}

	public static String getEndStationError() {
		return EndStationException;
	}

	/**
	 * Prüfung nach vollständiger Eingabe
	 */
	private boolean isValidInput() {
		if (jTextBauwerk.getText().isEmpty()) {
			JOptionPane.showMessageDialog(this, BauwerkException,
					"Fehlendes Bauwerk", JOptionPane.WARNING_MESSAGE);
			return false;
		} else if (jTextStationA.getText().isEmpty()) {
			JOptionPane.showMessageDialog(this, BauwerkException,
					"Fehlende Stationierung", JOptionPane.WARNING_MESSAGE);
			return false;
		} else if (!jTextStationE.getText().isEmpty()) {
			if (Double.valueOf(jTextStationE.getText()) <= Double
					.valueOf(jTextStationA.getText())) {
				JOptionPane.showMessageDialog(this, EndStationException,
						"Falscher Wert für Endstationierung",
						JOptionPane.WARNING_MESSAGE);
				return false;
			}
		}
		return true;
	}

	/**
	 * Löschen einer Reihe in der Tabelle
	 */
	private void deleteSelectedRow() {
		int selectedRowIndex = table.getSelectedRow();
		if (selectedRowIndex > -1) {
			BauwerkslinienDAO removedDAO = table
					.removeBauwerkslinienElement(selectedRowIndex);
			Manager.getInstance().addProjektChange(
					new RemoveProjektElement(removedDAO));
		}

	}

	private int returnValue = 0;

	// Deklaration der Variabeln
	private javax.swing.JButton jButtonCancel;

	private javax.swing.JButton jButtonNext;

	private javax.swing.JButton jButtonOK;

	private javax.swing.JLabel jLabel1;

	private javax.swing.JLabel jLabel2;

	private javax.swing.JLabel jLabel3;

	private javax.swing.JLabel jLabel4;

	private javax.swing.JLabel jLabel5;

	private javax.swing.JLabel jLabel6;

	private javax.swing.JLabel jLabel7;

	private javax.swing.JLabel jLabel8;

	private javax.swing.JLabel jLabel9;

	private javax.swing.JScrollPane jScrollPane2;

	private BauwerkslinienTable table;

	private javax.swing.JTextField jTextBauwerk;

	private javax.swing.JTextField jTextBesonderh;

	private DoubleTextField jTextHoeheBauwerk;

	private DoubleTextField jTextStationA;

	private DoubleTextField jTextStationE;

	@Override
	public void keyPressed(KeyEvent e) {
		if (e.getSource() == table) {
			if (e.getKeyCode() == KeyEvent.VK_DELETE) {
				deleteSelectedRow();
			}
		} else if (e.getSource() == jButtonCancel) {
			if (e.getKeyCode() == KeyEvent.VK_ENTER) {
				jButtonCancel.doClick();
			}
		} else if (e.getSource() == jButtonOK) {
			if (e.getKeyCode() == KeyEvent.VK_ENTER) {
				jButtonOK.doClick();
			}
		} else if (e.getSource() == jButtonNext) {
			if (e.getKeyCode() == KeyEvent.VK_ENTER) {
				jButtonNext.doClick();
			}
		}
	}

	@Override
	public void keyReleased(KeyEvent arg0) {

	}

	@Override
	public void keyTyped(KeyEvent arg0) {

	}

	@Override
	public void mouseClicked(MouseEvent e) {
		// bei Doppelklick auf eine Zeile in der Tabelle die Daten des
		// zugehörigen Elements in den Eingabefeldern anzeigen
		if (e.getClickCount() == 2) {
			int row = table.rowAtPoint(e.getPoint());
			element2Edit = table.getElementAtRow(row);
			if (element2Edit != null) {
				loadElement(element2Edit);
			}
		}
	}

	/**
	 * Bauwerkselemente aus der XML laden
	 * 
	 * @param dao
	 */
	private void loadElement(BauwerkslinienDAO dao) {
		clearInput();
		jTextStationA
				.setText(format1.format((dao.getStationierungVonInMeter())));
		jTextBauwerk.setText(dao.getBauwerk().toString());
		if (dao.getHoeheInMeter() != 0) {
			jTextHoeheBauwerk.setText(format1.format((dao.getHoeheInMeter())));
		}
		if (dao.getStationierungBisInMeter() != 0) {
			jTextStationE.setText(format1.format((dao
					.getStationierungBisInMeter())));
		}
		if (dao.getBesonderheiten() != null) {
			jTextBesonderh.setText(dao.getBesonderheiten());
		}
		jTextStationA.requestFocusInWindow();
	}

	@Override
	public void mouseEntered(MouseEvent arg0) {

	}

	@Override
	public void mouseExited(MouseEvent arg0) {

	}

	@Override
	public void mousePressed(MouseEvent arg0) {

	}

	@Override
	public void mouseReleased(MouseEvent arg0) {

	}
}
